import cgi
import os
import re
import logging
import wsgiref.handlers

from google.appengine.ext import webapp
from google.appengine.api import mail
from google.appengine.ext import db
from google.appengine.ext.webapp import template
from itertools import chain


class Page(db.Model):
  name =  db.StringProperty()
  attribute_name = db.StringProperty()
  int = db.IntegerProperty()
  string_list = db.StringListProperty()
  type = db.IntegerProperty() #  int = 1 , list = 2

class Results(db.Model):
    name =  db.StringProperty()
    values = db.StringListProperty()

class Attribute(db.Model):
    name =  db.StringProperty()
    value = db.StringProperty()    
    type = db.IntegerProperty()

# Retrives the appropiate value for page object accroding to type
def get_value(page):
  if page.type == 1:
    return str(page.int)
  elif page.type == 2:
    return ','.join(page.string_list)
    
class View(webapp.RequestHandler):
  def get(self,name):
    name = name.lower()
    page = Page.all().filter("name = ",name).get()
    
    if page:
      pages = Page.all().filter("name =", name).fetch(1000)
      results = []
      for p in pages:
        results += [Attribute(name=p.attribute_name,value=get_value(p),type=p.type)]
      
      template_values = {
        'page_name': name.capitalize(),
        'attributes': results
        }
      
      path = os.path.join(os.path.dirname(__file__),'view.html')
      
    else:
      template_values = {
      'page_name': name.capitalize()
      }
      path = os.path.join(os.path.dirname(__file__),'create.html')
      
    self.response.out.write(template.render(path, template_values))

class Edit(webapp.RequestHandler):
  def get(self,name,attribute=''):
    
    name = name.lower()
    attribute = attribute.lower()
    
    page = Page.all().filter("name =",name).get()
    
    if page:      
      pages = Page.all().filter("name =",name)
      
      results = []
      for p in pages:
        results += [Attribute(name=p.attribute_name,value=get_value(p),type=p.type)]
      
      edit_page = Page.all().filter("name =", name).filter("attribute_name =",attribute).get()
      
      if edit_page: 
       edit_attrib = Attribute(name=edit_page.attribute_name,value=get_value(edit_page),type=p.type)
      else:
       edit_attrib = Attribute(name='',value='',type=2) 
      
      template_values = {
        'page_name': name.capitalize(),
        'attributes': results,
        'edit' : edit_attrib
      }
      
    else:
      # Create a new page
      page = Page(name='',attribute_name='')
    
      template_values = {
        'page_name': name.capitalize(),
        'attributes': '',
        'edit' : page
      }  
      
    path = os.path.join(os.path.dirname(__file__),'edit.html')
    self.response.out.write(template.render(path, template_values))    
  
  def post(self,name):
    
    attribute = self.request.get('name').strip().lower()
    value = self.request.get('val').strip().lower()
    name = name.lower()
    
    page = Page.all().filter("name =", name).filter("attribute_name =",attribute).get()
    
    if not page:
      page = Page()
    
    p_int = re.compile('[0-9]+?') # integer
    p_string = re.compile('[a-z0-9_,]+?') # strings
    
    if p_int.match(value):
      logging.error('value %s is an integer' % value)
      page.int = int(value)
      page.type = 1
    
    elif p_string.match(value):
      page.string_list = value.split(',')
      page.type = 2
      logging.error('value %s is an list' % value)
      
    else:
      # error
      logging.error('value does not match any expression %s' %value)
      self.error(500)
      
    
    p_attrib = re.compile('[a-z_]+?') # strings
    
    if p_attrib.search(attribute):
      page.name = name
      page.attribute_name = attribute
      page.put()
      self.redirect('/wiki/' + name)
    else:
      # error
      self.error(500)
    
class Query(webapp.RequestHandler):
  def get(self):
    path = os.path.join(os.path.dirname(__file__),'home.html')
    self.response.out.write(template.render(path, {'':''}))    
  def post(self):
    path = os.path.join(os.path.dirname(__file__),'home.html')
    query_rows = self.request.get('query_rows')
    query_cols = self.request.get('query_cols')
    
    if query_rows.strip() == "" or query_cols.strip() == "":
      self.response.out.write(template.render(path, {'':''}))      
    else:  
      try:
        names = query_rows.lower().strip().split(' ')
        properties = query_cols.lower().strip().split(' ')
        error_message = ''
        exist = 0
        # work around for OR
        results = []
          
        for name in names:
          if name.count('.'):
            
            splitname = name.split('.')
            list_names = Page.all().filter("attribute_name =", splitname[1]).filter("name = ",splitname[0]).get()
            
            if list_names:
              for list in list_names.string_list:
                result = Results()
                result.name = list
                for property in properties:
                  rt = Page.all().filter("attribute_name =", property).filter("name = ",list).get()
                  if rt:
                    if not str(rt.int) == 'None':
                      result.values += [str(rt.int)]
                    else:
                      result.values += ["-"]
                      exist = 1
                  else:
                    result.values += ["-"]
                    exist = 1
                results += [result]
            else:
              error_message = "Oops " + splitname[0].capitalize() +  " does not have an list attribute named " + splitname[1]
              raise self.e
          else:
            result = Results()
            result.name = name
            for property in properties:
              r = Page.all().filter("attribute_name =", property).filter("name = ",name).get()
              if r:
                if not str(r.int) == 'None':
                  result.values += [str(r.int)]
                else:
                  result.values += ["-"]
                  exist = 1
              else:
                result.values += ["-"]
                exist = 1
            results += [result] 
          
        # remove first set of results - Again a work around
          
        template_values = {
          'query_rows': query_rows,
          'query_cols': query_cols,
          'all_not_exist': exist,
          'headers': properties, # TODO fix this it should only add the headers if actual property was found
          'results': results
        }
        self.response.out.write(template.render(path, template_values))    
      except:
        self.response.out.write(template.render(path, {'error':error_message}))    

class About(webapp.RequestHandler):
  def get(self):
    path = os.path.join(os.path.dirname(__file__),'about.html')
    self.response.out.write(template.render(path, {'e': 'e'}))    
class Feedback(webapp.RequestHandler):
  def get(self):
  # add error handling
    path = os.path.join(os.path.dirname(__file__),'feedback.html')
    self.response.out.write(template.render(path, {'e': 'e'}))    
  def post(self):
    mail.send_mail(sender="jorgensen.ian@gmail.com",
              to="jorgensen.ian@daatum.org",
              subject= "Feeback from " + self.request.get('name'),
              body= self.request.get('email') + " " +self.request.get('comments'))
    template_values = {
      'e': 'e',
    }  
    path = os.path.join(os.path.dirname(__file__),'feedback_sent.html')
    self.response.out.write(template.render(path, template_values))    
def gen_or(klass, field, items):
        return chain((klass.all().filter("%s =" % field, item) for item in items)) 
        
def main():
  application = webapp.WSGIApplication(
                                        [('/wiki/([^/.,]+)/edit', Edit),
                                        ('/wiki/([^/.,]+)/edit/([^/.,]+)', Edit),
                                        ('/wiki/([^/.,]+)/save', Edit),
                                        ('/feedback', Feedback),
										('/about', About),
                                        ('/wiki/([^/.,]+)', View),
                                        ('/',Query)],
                                        debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
  main()